package com.cyc.common.model;

import com.cyc.common.exception.BaseException;
import com.cyc.common.exception.ErrorType;
import com.cyc.common.exception.SystemErrorType;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;

/**
 * @author fei
 */
@ApiModel(description = "Api请求的返回模型，所有Api正常都返回该类的对象")
@Getter
public class ApiResult<T> {

    public static final String SUCCESSFUL_CODE = "200";
    public static final String SUCCESSFUL_MSG = "操作成功";

    @ApiModelProperty(value = "处理结果code", required = true)
    private String code;
    @ApiModelProperty(value = "处理结果描述信息")
    private String message;
    @ApiModelProperty(value = "请求结果生成时间戳")
    private long time;
    @ApiModelProperty(value = "处理结果数据信息")
    private T data;
    @Setter
    @ApiModelProperty(value = "流水号")
    private String requestId;

    public ApiResult() {
        this.time = System.currentTimeMillis();
    }

    /**
     * @param errorType 错误相应枚举
     */
    public ApiResult(ErrorType errorType) {
        this.code = errorType.getCode();
        this.message = errorType.getMsg();
        this.time = System.currentTimeMillis();
        this.requestId = null;
    }

    /**
     * @param errorType 错误相应枚举
     * @param data 返回信息
     */
    public ApiResult(ErrorType errorType, T data) {
        this(errorType);
        this.data = data;
    }

    /**
     * 内部使用，用于构造成功的结果
     *
     * @param code 响应码
     * @param message 相应信息
     * @param data 返回数据
     */
    private ApiResult(String code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
        this.time = System.currentTimeMillis();
        this.requestId = null;
    }

    /**
     * 内部使用，用于构造成功的结果
     *
     * @param code 响应码
     * @param message 相应信息
     * @param data 返回数据
     */
    private ApiResult(String code, String message, T data, String requestId) {
        this.code = code;
        this.message = message;
        this.data = data;
        this.time = System.currentTimeMillis();
        this.requestId = requestId;
    }

    /**
     * 快速创建成功结果并返回结果数据
     *
     * @param data 返回数据
     * @return Result
     */
    public static <T> ApiResult<T> success(T data) {
        return new ApiResult<T>(SUCCESSFUL_CODE, SUCCESSFUL_MSG, data);
    }

    /**
     * 快速创建成功结果
     *
     * @return Result
     */
    public static <T> ApiResult<T> success() {
        return success(null);
    }

    /**
     * 系统异常类没有返回数据
     *
     * @return Result
     */
    public static <T> ApiResult<T> fail() {
        return new ApiResult<T>(SystemErrorType.SYSTEM_ERROR);
    }

    /**
     * 系统异常类没有返回数据
     *
     * @param baseException 基本异常返回
     * @return Result
     */
    public static <T> ApiResult<T> fail(BaseException baseException) {
        return fail(baseException, null);
    }

    /**
     * 系统异常类并返回结果数据
     *
     * @param data 返回数据
     * @return Result
     */
    public static <T> ApiResult<T> fail(BaseException baseException, T data) {
        return new ApiResult<T>(baseException.getErrorType(), data);
    }

    /**
     * 系统异常类并返回结果数据
     *
     * @param errorType 错误枚举
     * @param data 返回数据
     * @return Result
     */
    public static <T> ApiResult<T> fail(ErrorType errorType, T data) {
        return new ApiResult<T>(errorType, data);
    }

    /**
     * 返回错误message
     * @param errorType 错误类型枚举
     * @param msg 错误信息
     * @return <T>
     */
    public static <T> ApiResult<T> fail(ErrorType errorType, String msg, String index) {
        ErrorType result = new ErrorType() {
            @Override
            public String getCode() {
                return errorType.getCode();
            }

            @Override
            public String getMsg() {
                return msg;
            }
        };
        return new ApiResult<T>(result, null);
    }

    /**
     * 系统异常类并返回结果数据
     *
     * @param errorType 错误类型枚举
     * @return Result
     */
    public static <T> ApiResult<T> fail(ErrorType errorType) {
        return ApiResult.fail(errorType, null);
    }

    /**
     * 系统异常类并返回结果数据
     *
     * @param data 返回信息
     * @return Result
     */
    public static <T> ApiResult<T> fail(T data) {
        return new ApiResult<T>(SystemErrorType.SYSTEM_ERROR, data);
    }


    /**
     * 成功code=000000
     *
     * @return true/false
     */
    @JsonIgnore
    public boolean isSuccess() {
        return SUCCESSFUL_CODE.equals(this.code);
    }

    /**
     * 失败
     *
     * @return true/false
     */
    @JsonIgnore
    public boolean isFail() {
        return !isSuccess();
    }


    /**
     * 生成返回结果
     *
     * @param code 返回状态码
     * @param msg 错误信息
     * @param data 返回数据
     * @return ApiResult<T>
     */
    public static <T> ApiResult<T> result(String code, String msg, T data) {
        return new ApiResult<T>(code, msg, data);
    }


    /**
     * 系统异常类没有返回数据
     *
     * @return Result
     */
    public static <T> ApiResult<T> fail(ApiResult<T> r) {
        return new ApiResult<T>(r.getCode(), r.getMessage(), r.getData());
    }


    @Override
    public String toString() {
        return "ApiResult{" +
                "code='" + code + '\'' +
                ", message='" + message + '\'' +
                ", time=" + time +
                ", data=" + data +
                '}';
    }
}
